package top.dotgo.dao.base;

import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPADeleteClause;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.querydsl.jpa.impl.JPAUpdateClause;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import top.dotgo.kit.SpringKit;
import top.dotgo.kit.bean.Page;
import top.dotgo.model.IBaseEntity;

import java.util.List;

/**
 * @author : lin
 * @date : 2019/10/11 16:31
 */
@NoRepositoryBean
public interface BaseDao<T extends IBaseEntity, P> extends JpaRepository<T, P>, QuerydslPredicateExecutor<T>, JpaSpecificationExecutor<T> {

    JPAQueryFactory FACTORY = SpringKit.getBean(JPAQueryFactory.class);

    /**
     * 条件更新
     *
     * @param obj            待更新对象
     * @param nullProperties 需要设置为空的属性
     * @param predicates     条件
     * @return 受影响行数
     */
    default long updateByWhere(T obj, List<Path<?>> nullProperties, Predicate... predicates) {
        JPAUpdateClause clause = FACTORY.update(Q.entityPath(obj));
        Q.setPathValue(clause, obj);
        if (nullProperties != null && !nullProperties.isEmpty()) {
            for (Path<?> property : nullProperties) {
                clause.setNull(property);
            }
        }
        if (predicates != null && predicates.length > 0 && predicates[0] != null) {
            clause.where(predicates);
        }

        return clause.execute();
    }

    /**
     * 条件删除
     *
     * @param predicates 条件
     * @return 受影响行数
     */
    default long delete(Class<T> clazz, Predicate... predicates) {
        JPADeleteClause clause = FACTORY.delete(Q.entityPath(clazz));
        if (predicates != null && predicates.length > 0 && predicates[0] != null) {
            clause.where(predicates);
        }
        return clause.execute();
    }

    /**
     * 条件查询数量
     *
     * @param predicates 条件
     * @return 数量
     */
    default long count(Class<T> clazz, Predicate... predicates) {
        JPAQuery<?> query = FACTORY.select().from(Q.entityPath(clazz));
        if (predicates != null && predicates.length > 0 && predicates[0] != null) {
            query.where(predicates);
        }
        return query.fetchCount();
    }

    /**
     * 条件查询首个
     *
     * @param expression 要查询的字段
     * @param predicates 条件
     * @param orders     排序
     * @return 结果
     */
    default T findFirst(Class<T> clazz, Expression<T> expression, List<Predicate> predicates, OrderSpecifier<?>... orders) {
        JPAQuery<T> query = FACTORY.select(expression)
                .from(Q.entityPath(clazz));
        if (predicates != null) {
            query.where(predicates.toArray(new Predicate[0]));
        }
        if (orders != null && orders.length > 0 && orders[0] != null) {
            for (OrderSpecifier<?> order : orders) {
                query.orderBy(order);
            }
        }
        return query.fetchFirst();
    }

    /**
     * 条件分页查询
     *
     * @param expression 要查询的字段
     * @param predicates 条件
     * @param page       页码
     * @param size       每页条数
     * @param orders     排序
     * @return Page<T>
     */
    default Page<T> findPage(Class<T> clazz, Expression<T> expression, List<Predicate> predicates, int page, int size, OrderSpecifier<?>... orders) {
        JPAQuery<T> query = FACTORY.select(expression)
                .from(Q.entityPath(clazz));
        if (predicates != null) {
            query.where(predicates.toArray(new Predicate[0]));
        }
        query.offset(Q.offset(page, size))
                .limit(size);
        if (orders != null && orders.length > 0 && orders[0] != null) {
            for (OrderSpecifier<?> order : orders) {
                query.orderBy(order);
            }
        }
        QueryResults<T> results = query.fetchResults();
        return Q.getPage(results);
    }

    /**
     * 条件查询列表
     *
     * @param expression 要查询的字段
     * @param predicates 条件
     * @param orders     排序
     * @return List<T>
     */
    default List<T> findList(Class<T> clazz, Expression<T> expression, List<Predicate> predicates, OrderSpecifier<?>... orders) {
        JPAQuery<T> query = FACTORY.select(expression)
                .from(Q.entityPath(clazz));
        if (predicates != null) {
            query.where(predicates.toArray(new Predicate[0]));
        }
        if (orders != null && orders.length > 0 && orders[0] != null) {
            for (OrderSpecifier<?> order : orders) {
                query.orderBy(order);
            }
        }
        return query.fetch();
    }

//    /**
//     * 获取 第一个 泛型类
//     *
//     * @return Class<T>
//     */
//    @SuppressWarnings("unchecked")
//    default Class<T> getClazz() {
//        return (Class<T>) TypeUtil.getTypeArgument(AopContext.currentProxy().getClass());
//    }

}

